package topology

import (
	"fmt"
	"hash/fnv"
	"sync"
)

// Node 表示网络中的一个节点（路由器或交换机）
type Node struct {
	ID         string                 `json:"id"`
	LocalNode  map[string]interface{} `json:"localNode"`
	Attributes map[string]interface{} `json:"attributes"`
	// 可以添加更多节点相关字段
}

// Link 表示网络中的一条链路（连接两个节点）
type Link struct {
	ID                string                 `json:"id"`
	LocalNode         map[string]interface{} `json:"localNode"`
	RemoteNode        map[string]interface{} `json:"remoteNode"`
	LinkDescriptor    map[string]interface{} `json:"linkDescriptor"`
	Attributes        map[string]interface{} `json:"attributes"`
	SourceNodeID      string                 `json:"sourceNodeId"`      // 源节点ID（计算得出）
	DestinationNodeID string                 `json:"destinationNodeId"` // 目标节点ID（计算得出）

	// 新增链路属性
	Bandwidth float64 `json:"bandwidth"` // 带宽(Mbps)
	Delay     float64 `json:"delay"`     // 时延(ms)
	Metric    uint32  `json:"metric"`    // 路由度量值
}

// Prefix 表示网络中的一个IP前缀
type Prefix struct {
	ID               string                 `json:"id"`
	LocalNode        map[string]interface{} `json:"localNode"`
	PrefixDescriptor map[string]interface{} `json:"prefixDescriptor"`
	// 可以添加更多前缀相关字段
}

// Manager 拓扑管理器，负责存储和管理网络拓扑信息
type Manager struct {
	mu       sync.RWMutex
	nodes    map[string]*Node   // 节点集合，键为节点ID
	links    map[string]*Link   // 链路集合，键为链路ID
	prefixes map[string]*Prefix // 前缀集合，键为前缀ID
}

// NewManager 创建新的拓扑管理器
func NewManager() *Manager {
	return &Manager{
		nodes:    make(map[string]*Node),
		links:    make(map[string]*Link),
		prefixes: make(map[string]*Prefix),
	}
}

// GetNodes 获取所有节点
func (m *Manager) GetNodes() []*Node {
	m.mu.RLock()
	defer m.mu.RUnlock()

	nodes := make([]*Node, 0, len(m.nodes))
	for _, node := range m.nodes {
		nodes = append(nodes, node)
	}
	return nodes
}

// GetNodesWithPagination 获取节点列表并支持分页
func (m *Manager) GetNodesWithPagination(page, size int64) ([]*Node, int64, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	// 参数校验
	if size <= 0 || page <= 0 {
		return nil, 0, fmt.Errorf("page 和 size 必须大于 0")
	}

	// 转换 map to slice
	nodes := make([]*Node, 0, len(m.nodes))
	for _, node := range m.nodes {
		nodes = append(nodes, node)
	}

	total := int64(len(nodes))

	// 计算起始和结束索引
	start := (page - 1) * size
	end := page * size

	if start >= total {
		return []*Node{}, total, nil
	}

	if end > total {
		end = total
	}

	// 分页
	paged := nodes[start:end]

	return paged, total, nil
}

// GetLinks 获取所有链路
func (m *Manager) GetLinks() []*Link {
	m.mu.RLock()
	defer m.mu.RUnlock()

	links := make([]*Link, 0, len(m.links))
	for _, link := range m.links {
		links = append(links, link)
	}
	return links
}

func (m *Manager) GetLinksWithPagination(page, size int64) ([]*Link, int64, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if size <= 0 || page <= 0 {
		return nil, 0, fmt.Errorf("page 和 size 必须大于 0")
	}

	links := make([]*Link, 0, len(m.links))
	for _, link := range m.links {
		links = append(links, link)
	}

	total := int64(len(links))

	start := (page - 1) * size
	end := page * size

	if start >= total {
		return []*Link{}, total, nil
	}

	if end > total {
		end = total
	}

	return links[start:end], total, nil
}

// GetPrefixes 获取所有前缀
func (m *Manager) GetPrefixes() []*Prefix {
	m.mu.RLock()
	defer m.mu.RUnlock()

	prefixes := make([]*Prefix, 0, len(m.prefixes))
	for _, prefix := range m.prefixes {
		prefixes = append(prefixes, prefix)
	}
	return prefixes
}

func (m *Manager) GetPrefixesWithPagination(page, size int64) ([]*Prefix, int64, error) {
	m.mu.RLock()
	defer m.mu.RUnlock()

	if size <= 0 || page <= 0 {
		return nil, 0, fmt.Errorf("page 和 size 必须大于 0")
	}

	prefixes := make([]*Prefix, 0, len(m.prefixes))
	for _, prefix := range m.prefixes {
		prefixes = append(prefixes, prefix)
	}

	total := int64(len(prefixes))

	start := (page - 1) * size
	end := page * size

	if start >= total {
		return []*Prefix{}, total, nil
	}

	if end > total {
		end = total
	}

	return prefixes[start:end], total, nil
}

// UpdateFromGoBGP 从GoBGP更新拓扑信息
func (m *Manager) UpdateFromGoBGP(nodes []*Node, links []*Link, prefixes []*Prefix) {
	m.mu.Lock()
	defer m.mu.Unlock()

	// 清空现有拓扑（简单实现，可优化为增量更新）
	m.nodes = make(map[string]*Node)
	m.links = make(map[string]*Link)
	m.prefixes = make(map[string]*Prefix)

	// 添加新节点
	for _, node := range nodes {
		// 生成节点ID（可根据实际数据结构调整）
		nodeID := generateNodeID(node.LocalNode)
		node.ID = nodeID
		m.nodes[nodeID] = node
	}

	// 添加新链路
	for _, link := range links {
		// 生成链路ID（可根据实际数据结构调整）
		linkID := generateLinkID(link.LocalNode, link.RemoteNode)
		link.ID = linkID

		// 计算源节点和目标节点ID
		link.SourceNodeID = generateNodeID(link.LocalNode)
		link.DestinationNodeID = generateNodeID(link.RemoteNode)

		// 从Attributes中提取链路属性
		extractLinkAttributes(link)

		m.links[linkID] = link
	}

	// 添加新前缀
	for _, prefix := range prefixes {
		// 生成前缀ID（可根据实际数据结构调整）
		prefixID := generatePrefixID(prefix.LocalNode, prefix.PrefixDescriptor)
		prefix.ID = prefixID
		m.prefixes[prefixID] = prefix
	}
}

// extractLinkAttributes 从链路属性中提取带宽、时延和metric
func extractLinkAttributes(link *Link) {
	// 从Attributes中提取链路属性
	if attrs, ok := link.Attributes["link"].(map[string]interface{}); ok {
		// 提取带宽（单位转换为Mbps）
		if bw, ok := getFloat64(attrs, "bandwidth"); ok {
			link.Bandwidth = bw / 1e6 // 从bps转换为Mbps
		}

		// 提取时延（单位保持ms）
		if delay, ok := getFloat64(attrs, "delay"); ok {
			link.Delay = delay
		}

		// 提取metric
		if metric, ok := getUint32(attrs, "metric"); ok {
			link.Metric = metric
		}
	}

	// 如果Attributes中没有，尝试从LinkDescriptor中提取
	// if desc, ok := link.LinkDescriptor.(map[string]interface{}); ok {
	// 	// 提取带宽（如果Attributes中没有）
	// 	if link.Bandwidth == 0 {
	// 		if bw, ok := getFloat64(desc, "maximumBandwidth"); ok {
	// 			link.Bandwidth = bw / 1e6 // 从bps转换为Mbps
	// 		}
	// 	}

	// 	// 提取metric（如果Attributes中没有）
	// 	if link.Metric == 0 {
	// 		if metric, ok := getUint32(desc, "igpMetric"); ok {
	// 			link.Metric = metric
	// 		}
	// 	}
	// }
}

// 辅助函数：从map中获取float64类型的值
func getFloat64(m map[string]interface{}, key string) (float64, bool) {
	if val, ok := m[key]; ok {
		switch v := val.(type) {
		case float64:
			return v, true
		case int:
			return float64(v), true
		case int64:
			return float64(v), true
		case uint:
			return float64(v), true
		case uint64:
			return float64(v), true
		}
	}
	return 0, false
}

// 辅助函数：从map中获取uint32类型的值
func getUint32(m map[string]interface{}, key string) (uint32, bool) {
	if val, ok := m[key]; ok {
		switch v := val.(type) {
		case uint32:
			return v, true
		case int:
			return uint32(v), true
		case int64:
			return uint32(v), true
		case uint:
			return uint32(v), true
		case uint64:
			return uint32(v), true
		case float64:
			return uint32(v), true
		}
	}
	return 0, false
}

// 辅助函数：生成节点ID
func generateNodeID(localNode map[string]interface{}) string {
	// 从localNode中提取唯一标识（如NodeID、RouterID等）
	// 这里需要根据实际的localNode结构调整
	if id, ok := localNode["nodeId"].(string); ok {
		return id
	}

	// 备选方案：使用哈希值
	return fmt.Sprintf("node-%x", hashMap(localNode))
}

// 辅助函数：生成链路ID
func generateLinkID(localNode, remoteNode map[string]interface{}) string {
	// 使用源节点和目标节点的ID组合
	srcID := generateNodeID(localNode)
	dstID := generateNodeID(remoteNode)

	// 可以添加链路描述符中的信息，如接口ID等
	return fmt.Sprintf("link-%s-%s", srcID, dstID)
}

// 辅助函数：生成前缀ID
func generatePrefixID(localNode map[string]interface{}, prefixDesc map[string]interface{}) string {
	// 使用节点ID和前缀地址组合
	nodeID := generateNodeID(localNode)

	// 从前缀描述符中提取地址和掩码
	if addr, ok := prefixDesc["prefixAddress"].(string); ok {
		if mask, ok := prefixDesc["prefixLength"].(int); ok {
			return fmt.Sprintf("prefix-%s-%s/%d", nodeID, addr, mask)
		}
	}

	// 备选方案：使用哈希值
	return fmt.Sprintf("prefix-%x", hashMap(prefixDesc))
}

// 辅助函数：计算map的哈希值（用于生成ID）
func hashMap(m map[string]interface{}) uint64 {
	h := fnv.New64a()

	// 对map中的每个键值对进行哈希
	for k, v := range m {
		h.Write([]byte(k))
		h.Write([]byte(fmt.Sprintf("%v", v)))
	}

	return h.Sum64()
}
